"use strict";

var _ = require("underscore"),
    S = require("string"),
    path = require("path"),
    C = require('../common.js'),
    Router = require('../router').Router,
    RouterWithView = require('../router').RouterWithView;

/**
 * The MVC-style router class.
 * @class MvcRouter
 */
module.exports = RouterWithView.extend({
    },
    /**
     * @lends MvcRouter
     */
    {
    /**
     * @method
     */
    mount: function(webModule, route, options, cb) {
        options = _.extend({
            hasModule: false,
            controllerPath: 'controllers',
            modelPath: 'models',
            defaultController: 'index',
            splitPostAction: true,
            defaultAction: 'index'
        }, options);

        var self = this;
        var mvcInfo = _.pick(options, [ 'modelPath' ]);

        function createRouter(req, res, next) {
            try {
                var nodes = [], modName, ctrlName;

                if (options.hasModule) {
                    modName = S(req.params.module).camelize();
                    nodes.push(modName);
                }

                ctrlName = S(req.params.controller || options.defaultController).camelize();
                nodes.push(ctrlName);

                var ctrlRelPath = nodes.join('/');
                if (ctrlRelPath.indexOf('..') >= 0) {
                    return Router.onError(webModule, req, res, C.HttpCode.HTTP_BAD_REQUEST);
                }

                var actName = S(req.params.action || options.defaultAction).camelize();
                if (actName.charAt(0) === '_') {
                    return Router.onError(webModule, req, res, C.HttpCode.HTTP_NOT_FOUND);
                }

                mvcInfo.controllerPath = C.urlJoin(options.controllerPath, ctrlRelPath);
                mvcInfo.action = (req.method.toLowerCase() === 'post' && options.splitPostAction) ? (actName + 'Postback') : actName;
                mvcInfo.view = ctrlRelPath + '_' + actName;

                req.router = new self(route, webModule, req, res, mvcInfo);
                next();

            } catch (error) {
                Router.onError(webModule, req, res, error);
            }
        }

        var engine = webModule.app.engine;

        Router.getMiddlewares(webModule, route, options.middlewares, function (err, middlewares) {
            if (err) return cb (err);

            middlewares.unshift(createRouter);
            middlewares.push(Router.dispatch);

            if (options.hasModule) {
                var r1 = C.urlJoin(route, '/:module/:controller/:action'),
                    r2 = C.urlJoin(route, '/:module/:controller'),
                    r3 = C.urlJoin(route, '/:module');

                engine.get(r1, middlewares);
                engine.post(r1, middlewares);
                engine.get(r2, middlewares);
                engine.post(r2, middlewares);
                engine.get(r3, middlewares);
                engine.post(r3, middlewares);
            } else {
                var r4 = C.urlJoin(route, '/:controller/:action'),
                    r5 = C.urlJoin(route, '/:controller');

                engine.get(r4, middlewares);
                engine.post(r4, middlewares);
                engine.get(r5, middlewares);
                engine.post(r5, middlewares);
                engine.get(route, middlewares);
                engine.post(route, middlewares);
            }

            cb();
        });
    }
});